#pragma once

template <size_t N>
constexpr size_t AddN = std::ratio_add<std::ratio<N>, std::ratio<1>>::num;

template <size_t N>
constexpr size_t DecN = std::ratio_subtract<std::ratio<N>, std::ratio<1>>::num;

template<size_t X, size_t N>
constexpr size_t PowN = std::ratio_multiply<std::ratio<X>, std::ratio<PowN<X, DecN<N>>>>::num;

template<size_t X>
constexpr size_t PowN<X, 0> = 1;

template<size_t X, size_t N, size_t R = 1>
constexpr size_t Sqrt = std::ratio_greater_v<std::ratio<PowN<R, N>>, std::ratio<X>> ? DecN<R> : Sqrt<X, N, AddN<R>>;

template<size_t X, size_t N>
constexpr size_t Sqrt<X, N, X> = X;
template<size_t N>
constexpr size_t Sqrt<2, N> = 1;
template<>
constexpr size_t Sqrt<2, 1> = 2;